import React, { useEffect, useState, useRef, useCallback } from 'react';
import EmojiPicker from 'emoji-picker-react'; // 引入 EmojiPicker
import { message as antdMessage } from 'antd'; // 修正导入名称，避免与变量冲突
import './Liaotian.css'; // 引入新的CSS文件

// 定义类型
interface ChatMessage {
  id: string;
  from: string;
  to: string;
  content: string | ArrayBuffer | null;
  timestamp: number | string;
  type: 'textMessage' | 'imageMessage' | 'videoMessage' | 'systemMessage' | string;
  isFlash?: boolean;
  metadata?: any;
  isLocalMessage?: boolean;
  isLargeVideo?: boolean;
  videoMetadata?: {
    filename?: string;
    filesize?: number;
    filetype?: string;
    duration?: number;
    thumbnail?: string;
  };
}

interface User {
  id: string;
  name: string;
  avatar?: string;
  status?: string;
}

interface IncomingCall {
  from: string;
  offer: RTCSessionDescriptionInit;
}

interface StateRef {
  callState: string;
  localStream: MediaStream | null;
  recipient: string;
  incomingCall: IncomingCall | null;
  callPartner: string | null;
  peerConnection: RTCPeerConnection | null;
  cleanupCall: () => void;
}

// 重连配置
const RECONNECT_TIMEOUT_BASE = 2000; // 初始重连延迟（毫秒）
const RECONNECT_TIMEOUT_MAX = 30000; // 最大重连延迟
// 本地环境配置
const USE_LOCALTUNNEL = false; // 设置为false禁用内网穿透
const LOCALTUNNEL_WS_URL = "localhost:3000/ws"; // 本地WebSocket地址
const LOCALTUNNEL_FRONTEND_URL = "localhost:5173"; // 本地前端地址

// 在页面加载时显示本地地址
if (USE_LOCALTUNNEL) {
  console.log(`
    ===========================================
    使用内网穿透访问:
    前端地址: https://${LOCALTUNNEL_FRONTEND_URL}
    WebSocket地址: wss://${LOCALTUNNEL_WS_URL}
    ===========================================
  `);
} else {
  console.log(`
    ===========================================
    使用本地环境访问:
    前端地址: http://${LOCALTUNNEL_FRONTEND_URL}
    WebSocket地址: ws://${LOCALTUNNEL_WS_URL}
    ===========================================
  `);
}

// WebRTC 配置，使用公共STUN服务器
const peerConnectionConfig: RTCConfiguration = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    { urls: 'stun:stun1.l.google.com:19302' },
    { urls: 'stun:stun2.l.google.com:19302' },
    { urls: 'stun:stun3.l.google.com:19302' },
    { urls: 'stun:stun4.l.google.com:19302' }
    // 本地环境不需要TURN服务器
  ],
  // 改为all，允许尝试直连和中继
  iceTransportPolicy: 'all' as RTCIceTransportPolicy,
  // 增加ICE候选者收集超时时间
  iceCandidatePoolSize: 10
};

export default function Liaotian() {
  // --- State and Refs ---
  const [userId, setUserId] = useState<string>('');
  const [isOnline, setIsOnline] = useState<boolean>(false);
  const [connectionStatus, setConnectionStatus] = useState<'offline' | 'connecting' | 'online' | 'reconnecting'>('offline');
  const [recipient, setRecipient] = useState<string>('');
  const [message, setMessage] = useState<string>('');
  const [chatLog, setChatLog] = useState<ChatMessage[]>([]);
  const [onlineUsers, setOnlineUsers] = useState<User[]>([]);
  const [hiddenUsers, setHiddenUsers] = useState<string[]>([]);
  const [showEmojiPicker, setShowEmojiPicker] = useState<boolean>(false);
  const [showContactList, setShowContactList] = useState<boolean>(true);
  // Lightbox 状态
  const [isLightboxOpen, setIsLightboxOpen] = useState<boolean>(false);
  const [currentImageIndex, setCurrentImageIndex] = useState<number>(0);
  const [chatImages, setChatImages] = useState<string[]>([]);
  // 闪图状态
  const [burnedMessageIds, setBurnedMessageIds] = useState<Set<string>>(new Set());
  const [activeFlashMessage, setActiveFlashMessage] = useState<ChatMessage | null>(null);
  // WebRTC 状态
  const [callState, setCallState] = useState<'idle' | 'calling' | 'receiving' | 'active'>('idle');
  const [incomingCall, setIncomingCall] = useState<IncomingCall | null>(null);
  const [localStream, setLocalStream] = useState<MediaStream | null>(null);
  const [remoteStream, setRemoteStream] = useState<MediaStream | null>(null);
  const [isFullScreen, setIsFullScreen] = useState<boolean>(false);
  const [callPartner, setCallPartner] = useState<string | null>(null);

  // 使用useRef来持有WebSocket实例、定时器和重连计数
  const socketRef = useRef<WebSocket | null>(null);
  const messagesEndRef = useRef<HTMLDivElement | null>(null);
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const flashFileInputRef = useRef<HTMLInputElement | null>(null);
  const videoFileInputRef = useRef<HTMLInputElement | null>(null);
  const reconnectTimerRef = useRef<NodeJS.Timeout | null>(null);
  const retryCountRef = useRef<number>(0);
  const emojiPickerRef = useRef<HTMLDivElement | null>(null);
  const peerConnectionRef = useRef<RTCPeerConnection | null>(null);
  const localVideoRef = useRef<HTMLVideoElement | null>(null);
  const remoteVideoRef = useRef<HTMLVideoElement | null>(null);
  const flashTimerRef = useRef<NodeJS.Timeout | null>(null);
  const videoContainerRef = useRef<HTMLDivElement | null>(null);
  const messageInputRef = useRef<HTMLInputElement | null>(null);

  // --- 状态同步桥梁 ---
  const stateRef = useRef<StateRef | null>(null);
  useEffect(() => {
    stateRef.current = {
      callState,
      localStream,
      recipient,
      incomingCall,
      callPartner,
      peerConnection: peerConnectionRef.current,
      cleanupCall: () => {
        console.log("cleanupCall: Cleaning up WebRTC resources.");
        if (peerConnectionRef.current) {
          peerConnectionRef.current.onicecandidate = null;
          peerConnectionRef.current.ontrack = null;
          peerConnectionRef.current.close();
          peerConnectionRef.current = null;
        }
        if (stateRef.current?.localStream) {
          stateRef.current.localStream.getTracks().forEach(track => track.stop());
        }
        setLocalStream(null);
        setRemoteStream(null);
        setCallState('idle');
        setIncomingCall(null);
        setCallPartner(null);
      }
    };
  });

  // 滚动到最新的消息
  const scrollToBottom = () => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  };

  useEffect(() => {
    scrollToBottom();
  }, [chatLog]);

  // 当选择联系人时自动隐藏联系人列表（仅在移动设备上）
  const handleSelectContact = (user: User) => {
    setRecipient(user.id);

    // 在移动设备上自动隐藏联系人列表
    if (window.innerWidth < 768) {
      setShowContactList(false);
    }
  };

  // 显示联系人列表
  const showContacts = () => {
    setShowContactList(true);
  };

  // 随着窗口大小变化自动调整联系人列表显示
  useEffect(() => {
    const handleResize = () => {
      if (window.innerWidth >= 768) {
        // 在大屏幕上始终显示联系人列表
        setShowContactList(true);
      }
    };

    window.addEventListener('resize', handleResize);
    handleResize(); // 初始检查

    return () => window.removeEventListener('resize', handleResize);
  }, []);

  // 聚焦到消息输入框
  useEffect(() => {
    // 确保消息输入框存在且聊天界面显示时聚焦
    if (messageInputRef.current && recipient) {
      setTimeout(() => {
        messageInputRef.current?.focus();
      }, 100);
    }
  }, [recipient]);

  // --- Lightbox 逻辑 ---
  const openLightbox = (clickedImageIndex: number) => {
    setCurrentImageIndex(clickedImageIndex);
    setIsLightboxOpen(true);
  };

  const closeLightbox = () => {
    setIsLightboxOpen(false);
  };

  const showNextImage = (e: React.MouseEvent) => {
    e.stopPropagation();
    setCurrentImageIndex(prevIndex => (prevIndex + 1) % chatImages.length);
  };

  const showPrevImage = (e: React.MouseEvent) => {
    e.stopPropagation();
    setCurrentImageIndex(prevIndex => (prevIndex - 1 + chatImages.length) % chatImages.length);
  };

  // 按 Esc 键关闭 Lightbox
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        closeLightbox();
      }
    };
    if (isLightboxOpen) {
      window.addEventListener('keydown', handleKeyDown);
    }
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [isLightboxOpen]);

  // 更新图片列表
  useEffect(() => {
    const images = chatLog
      .filter(log =>
        log.type === 'imageMessage' &&
        !log.isFlash && // 确保不是闪图
        ((log.from === userId && log.to === recipient) || (log.from === recipient && log.to === userId))
      )
      .map(log => log.content)
      .filter((content): content is string => typeof content === 'string');
    setChatImages(images);
  }, [chatLog, recipient, userId]);

  // --- Emoji Picker 逻辑 ---
  interface EmojiClickData {
    emoji: string;
  }

  const handleEmojiClick = (emojiObject: EmojiClickData) => {
    setMessage(prevMessage => prevMessage + emojiObject.emoji);
    setShowEmojiPicker(false);
  };

  // 点击外部关闭 Emoji Picker
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (emojiPickerRef.current && !emojiPickerRef.current.contains(event.target as Node)) {
        // 这里需要额外判断点击的是否是表情按钮本身，防止按钮无法切换
        if (!(event.target as Element).closest('.emoji-button')) {
          setShowEmojiPicker(false);
        }
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, []);

  // --- 闪图逻辑 (修复版) ---
  const handleViewFlashImage = (message: ChatMessage) => {
    setActiveFlashMessage(message);
    flashTimerRef.current = setTimeout(() => {
      setActiveFlashMessage(null);
    }, 5000);
  };

  // --- 通用的消息发送函数 ---
  const sendPayload = useCallback((payload: { type: string; to?: string;[key: string]: any }) => {
    if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
      socketRef.current.send(JSON.stringify(payload));
    } else {
      console.error("无法发送消息，WebSocket 未连接。");
    }
  }, []);

  // --- 新增：专门用于处理远程视频流的 Effect ---
  useEffect(() => {
    if (remoteVideoRef.current && remoteStream) {
      console.log('Attaching remote stream to video element.');
      remoteVideoRef.current.srcObject = remoteStream;
    }
  }, [remoteStream]);

  // --- 全新增强的视频播放逻辑 ---
  useEffect(() => {
    const videoEl = remoteVideoRef.current;
    if (videoEl && remoteStream) {
      console.log('远程视频流已更新，正在重新挂载...');

      // 1. 将媒体流附加到video元素
      videoEl.srcObject = remoteStream;

      // 2. 确保video元素没有被静音
      videoEl.muted = false;

      // 3. 设置关键播放属性
      videoEl.autoplay = true;
      videoEl.playsInline = true;

      // 4. 创建一个更健壮的视频播放处理函数
      const playVideo = async () => {
        console.log('尝试播放远程视频...');
        try {
          await videoEl.play();
          console.log('✅ 远程视频播放成功！');
        } catch (error: unknown) {
          console.error('❌ 远程视频自动播放失败:', error);

          // 如果自动播放失败，尝试静音播放（浏览器通常允许静音自动播放）
          if (error instanceof Error && error.name === 'NotAllowedError') {
            console.log('自动播放被阻止，尝试静音播放...');
            videoEl.muted = true;
            try {
              await videoEl.play();
              console.log('静音模式下远程视频播放成功！');
              // 显示一个按钮让用户手动点击取消静音
              antdMessage.info('请点击视频画面取消静音');
            } catch (err) {
              console.error('静音模式下播放也失败:', err);
              antdMessage.error('无法播放远程视频，请检查浏览器设置');

              // 创建一个覆盖在视频上的播放按钮
              const playButton = document.createElement('button');
              playButton.textContent = '点击播放视频';
              playButton.style.position = 'absolute';
              playButton.style.top = '50%';
              playButton.style.left = '50%';
              playButton.style.transform = 'translate(-50%, -50%)';
              playButton.style.zIndex = '1000';
              playButton.style.padding = '10px 20px';
              playButton.style.backgroundColor = '#007bff';
              playButton.style.color = 'white';
              playButton.style.border = 'none';
              playButton.style.borderRadius = '5px';
              playButton.style.cursor = 'pointer';

              if (videoContainerRef.current) {
                videoContainerRef.current.appendChild(playButton);

                playButton.onclick = async () => {
                  try {
                    await videoEl.play();
                    playButton.remove();
                  } catch (e) {
                    console.error('用户交互后播放仍然失败:', e);
                    antdMessage.error('播放失败，请刷新页面重试');
                  }
                };
              }
            }
          }
        }
      };

      // 5. 添加多种事件监听器，确保在不同时机尝试播放
      const eventHandlers = {
        loadedmetadata: () => {
          console.log("远程视频元数据加载完毕");
          playVideo();
        },
        canplay: () => {
          console.log("浏览器认为远程视频可以播放了");
          playVideo();
        },
        playing: () => {
          console.log("远程视频开始播放");
        },
        pause: () => {
          console.log("远程视频已暂停");
        },
        stalled: () => {
          console.log("远程视频播放停滞");
        },
        waiting: () => {
          console.log("远程视频等待数据中");
        },
        error: (e: Event) => {
          console.error("远程视频元素错误:", e);
        }
      };

      // 6. 注册所有事件监听器
      Object.entries(eventHandlers).forEach(([event, handler]) => {
        videoEl.addEventListener(event, handler);
      });

      // 7. 添加点击事件来处理用户交互
      const handleVideoClick = () => {
        if (videoEl.muted) {
          videoEl.muted = false;
          antdMessage.success('已取消静音');
        }
        playVideo();
      };
      videoEl.addEventListener('click', handleVideoClick);

      // 8. 立即尝试播放
      playVideo();

      // 9. 返回一个清理函数
      return () => {
        // 移除所有事件监听器
        Object.entries(eventHandlers).forEach(([event, handler]) => {
          videoEl.removeEventListener(event, handler);
        });
        videoEl.removeEventListener('click', handleVideoClick);

        // 移除可能添加的播放按钮
        if (videoContainerRef.current) {
          const playButton = videoContainerRef.current.querySelector('button');
          if (playButton) {
            playButton.remove();
          }
        }
      };
    } else if (videoEl) {
      console.log('清除远程视频元素');
      videoEl.srcObject = null;
    }
  }, [remoteStream]);

  // --- 全新重构的 WebRTC 核心逻辑 ---

  const handleHangUpClick = useCallback(() => {
    if (stateRef.current) {
      const { cleanupCall, callPartner: currentCallPartner } = stateRef.current;
      if (currentCallPartner) {
        console.log(`handleHangUpClick: Sending 'end-call' to ${currentCallPartner}.`);
        sendPayload({ type: 'end-call', to: currentCallPartner });
      }
      cleanupCall();
    }
  }, [sendPayload]);

  const initializePeerConnection = useCallback((stream: MediaStream) => {
    console.log('--- Initializing Peer Connection with enhanced config ---');
    console.log('ICE服务器配置:', JSON.stringify(peerConnectionConfig.iceServers));

    const pc = new RTCPeerConnection(peerConnectionConfig);

    // 增强的连接状态监控
    pc.onconnectionstatechange = () => {
      console.log(`Connection State: ${pc.connectionState}`);
      if (pc.connectionState === 'connected') {
        console.log('✅ WebRTC连接成功建立！');
        // 记录选中的ICE候选者信息
        const selectedCandidatePair = pc.sctp?.transport?.iceTransport?.getSelectedCandidatePair();
        if (selectedCandidatePair) {
          console.log('选中的ICE候选者对:', selectedCandidatePair);
        }
      } else if (pc.connectionState === 'failed' || pc.connectionState === 'disconnected') {
        console.log('❌ WebRTC连接失败或断开，正在尝试使用TURN服务器');
        // 记录当前使用的服务器
        console.log('当前使用的ICE服务器:', pc.getConfiguration().iceServers);

        // 通知用户 - 修复message.error调用
        antdMessage.error('视频通话连接失败，请确保TURN服务器配置正确');

        // 尝试重新连接
        if (stateRef.current && stateRef.current.callState !== 'idle') {
          setTimeout(() => {
            console.log('尝试重新建立连接...');
            if (stateRef.current) {
              stateRef.current.cleanupCall();
            }
          }, 2000);
        }
      } else if (pc.connectionState === 'closed') {
        console.log('WebRTC连接已关闭');
      }
    };

    // 添加ICE连接状态监控
    pc.oniceconnectionstatechange = () => {
      console.log(`ICE Connection State: ${pc.iceConnectionState}`);
      if (pc.iceConnectionState === 'failed') {
        console.log('ICE连接失败，检查TURN服务器配置');

        // 尝试重启ICE
        if (pc.restartIce) {
          console.log('尝试重启ICE连接...');
          pc.restartIce();
        }
      }
    };

    // 添加ICE收集状态监控
    pc.onicegatheringstatechange = () => {
      console.log(`ICE Gathering State: ${pc.iceGatheringState}`);

      // 在ICE收集完成后检查候选者类型
      if (pc.iceGatheringState === 'complete') {
        console.log('ICE候选者收集完成，检查候选者类型...');

        // 获取本地候选者统计
        let hasHostCandidate = false;
        let hasServerReflexiveCandidate = false;
        let hasRelayCandidate = false;

        // 如果浏览器支持，获取ICE候选者统计
        if (pc.getStats) {
          pc.getStats().then(stats => {
            stats.forEach(report => {
              if (report.type === 'local-candidate') {
                console.log(`本地候选者: ${report.candidateType}, ${report.protocol}, ${report.ip}:${report.port}`);
                if (report.candidateType === 'host') hasHostCandidate = true;
                if (report.candidateType === 'srflx') hasServerReflexiveCandidate = true;
                if (report.candidateType === 'relay') hasRelayCandidate = true;
              }
            });

            console.log('候选者类型统计:', {
              host: hasHostCandidate,
              srflx: hasServerReflexiveCandidate,
              relay: hasRelayCandidate
            });

            if (!hasRelayCandidate) {
              console.warn('⚠️ 未生成中继(TURN)候选者，TURN服务器可能配置有误');
            }
          }).catch(err => {
            console.error('获取候选者统计失败:', err);
          });
        }
      }
    };

    pc.onicecandidate = (event) => {
      if (event.candidate) {
        console.log("Generated ICE candidate:", event.candidate.candidate);
        // 解析候选者类型
        let candidateType = '未知';
        try {
          const candidateStr = event.candidate.candidate;
          if (candidateStr.includes('typ host')) candidateType = 'host(本地)';
          else if (candidateStr.includes('typ srflx')) candidateType = 'srflx(STUN)';
          else if (candidateStr.includes('typ relay')) candidateType = 'relay(TURN)';

          console.log(`候选类型: ${candidateType}, 协议: ${event.candidate.protocol || '未知'}`);
        } catch (e) {
          console.error('解析候选者类型失败:', e);
        }

        if (stateRef.current && stateRef.current.callPartner) {
          sendPayload({
            type: 'webrtc-ice-candidate',
            to: stateRef.current.callPartner,
            candidate: event.candidate
          });
        }
      } else {
        console.log("ICE候选收集完成");
      }
    };

    pc.ontrack = (event) => {
      console.log('!!! ONTRACK EVENT FIRED !!!');
      if (event.streams && event.streams[0]) {
        console.log('Remote stream received:', event.streams[0]);
        console.log('Remote stream tracks:', event.streams[0].getTracks().map(t => `${t.kind}(${t.id}, enabled=${t.enabled})`));

        // 检查轨道状态
        event.streams[0].getTracks().forEach(track => {
          track.onended = () => console.log(`轨道已结束: ${track.kind}`);
          track.onmute = () => console.log(`轨道已静音: ${track.kind}`);
          track.onunmute = () => console.log(`轨道已取消静音: ${track.kind}`);
        });

        setRemoteStream(event.streams[0]);
      } else {
        console.error('onTrack event fired but no streams found!');
      }
    };

    // 确保先添加本地媒体轨道
    if (stream) {
      console.log('Adding local stream tracks to peer connection:', stream.getTracks().map(t => `${t.kind}(${t.id})`));
      stream.getTracks().forEach(track => {
        console.log(`Adding track: ${track.kind} (${track.id}, enabled=${track.enabled})`);
        pc.addTrack(track, stream);
      });
    } else {
      console.error('initializePeerConnection called without a stream!');
    }

    peerConnectionRef.current = pc;
    return pc;
  }, [sendPayload]);

  // 修改startCall函数，确保正确的信令顺序
  const startCall = useCallback(async (stream: MediaStream) => {
    if (!stateRef.current || !stateRef.current.recipient) return alert('请先选择一个聊天对象！');

    console.log('Starting call with stream:', stream);
    setCallState('calling');

    // 初始化连接并添加本地媒体
    const pc = initializePeerConnection(stream);

    // 记录并显示所有可用的连接接口
    console.log('--- 本机网络接口信息 ---');
    try {
      const interfaces = await getLocalNetworkInterfaces();
      console.log('可用网络接口:', interfaces);
    } catch (err) {
      console.error('获取网络接口失败:', err);
    }

    try {
      // 创建并设置本地描述
      console.log('Creating offer...');
      const offer = await pc.createOffer({
        offerToReceiveAudio: true,
        offerToReceiveVideo: true,
        // voiceActivityDetection: false, // 移除不支持的属性
        iceRestart: true // 强制ICE重启，增加连接成功率
      });

      console.log('Setting local description (offer):', offer.sdp);
      await pc.setLocalDescription(offer);

      // 发送offer给对方
      console.log('Sending offer to peer');
      if (stateRef.current && stateRef.current.recipient) {
        sendPayload({ type: 'start-call', to: stateRef.current.recipient, offer });
      }

      // 增加ICE超时检测
      setTimeout(() => {
        if (pc.iceConnectionState !== 'connected' && pc.iceConnectionState !== 'completed') {
          console.warn('ICE连接超时，尝试使用TURN中继...');
          // 强制使用中继候选者
          if (stateRef.current && stateRef.current.recipient) {
            sendPayload({
              type: 'ice-timeout',
              to: stateRef.current.recipient,
              message: '连接超时，建议检查防火墙设置'
            });
          }
        }
      }, 10000);
    } catch (err: unknown) {
      console.error('Error during call start:', err);
      if (err instanceof Error) {
        alert('启动通话时出错: ' + err.message);
      } else {
        alert('启动通话时出错');
      }
    }
  }, [initializePeerConnection, sendPayload]);

  // 辅助函数：获取本地网络接口信息
  const getLocalNetworkInterfaces = async () => {
    try {
      // 使用WebRTC获取本地IP地址
      const pc = new RTCPeerConnection({ iceServers: [] });
      pc.createDataChannel('');
      await pc.createOffer().then(offer => pc.setLocalDescription(offer));

      interface NetworkInterface {
        type: string;
        address?: string;
        candidate: string;
      }

      return new Promise<NetworkInterface[]>(resolve => {
        const interfaces: NetworkInterface[] = [];

        pc.onicecandidate = (event) => {
          if (!event.candidate) {
            pc.close();
            resolve(interfaces);
            return;
          }

          const candidate = event.candidate.candidate;
          if (candidate && candidate.includes('typ host')) {
            const match = candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3})/);
            if (match) {
              interfaces.push({
                type: 'local',
                address: match[1],
                candidate: candidate
              });
            }
          } else if (candidate) {
            interfaces.push({
              type: 'other',
              candidate: candidate
            });
          }
        };

        // 10秒超时
        setTimeout(() => {
          pc.close();
          resolve(interfaces);
        }, 5000);
      });
    } catch (e) {
      console.error('获取网络接口失败:', e);
      return [];
    }
  };

  // 修改answerCall函数，确保正确的信令顺序
  const answerCall = useCallback(async (stream: MediaStream) => {
    if (!stateRef.current || !stateRef.current.incomingCall) return;

    console.log('Answering call with stream:', stream);
    setCallState('active');

    // 初始化连接并添加本地媒体
    const pc = initializePeerConnection(stream);

    try {
      // 设置远程描述（对方的offer）
      console.log('Setting remote description (offer)');
      if (stateRef.current && stateRef.current.incomingCall) {
        await pc.setRemoteDescription(new RTCSessionDescription(stateRef.current.incomingCall.offer));
      }

      // 创建并设置本地描述
      console.log('Creating answer...');
      const answer = await pc.createAnswer({
        // voiceActivityDetection: false // 移除不支持的属性
      });

      console.log('Setting local description (answer):', answer.sdp);
      await pc.setLocalDescription(answer);

      // 发送answer给对方
      console.log('Sending answer to peer');
      if (stateRef.current && stateRef.current.incomingCall) {
        sendPayload({ type: 'webrtc-answer', to: stateRef.current.incomingCall.from, answer });
      }

      setIncomingCall(null);
    } catch (err: unknown) {
      console.error('Error during call answer:', err);
      if (err instanceof Error) {
        alert('接听通话时出错: ' + err.message);
      } else {
        alert('接听通话时出错');
      }
    }
  }, [initializePeerConnection, sendPayload]);

  const getMedia = useCallback(async () => {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
      return stream;
    } catch (error: unknown) {
      console.error('获取媒体设备失败:', error);

      // 处理不同类型的媒体错误
      if (error instanceof Error) {
        const mediaError = error as Error & { name?: string };

        // 提供更具体的反馈
        if (mediaError.name === 'NotAllowedError' || mediaError.name === 'PermissionDeniedError') {
          alert('您拒绝了摄像头和麦克风的使用权限。请在浏览器地址栏左侧的锁形图标中，重新允许权限。');
        } else if (mediaError.name === 'NotFoundError' || mediaError.name === 'DevicesNotFoundError') {
          alert('未找到可用的摄像头或麦克风设备。请检查设备是否已正确连接。');
        } else if (mediaError.name === 'TypeError') {
          // 专门处理TypeError
          alert('浏览器无法访问媒体设备。这可能是由于：\n1. 您的浏览器不支持该功能\n2. 您正在使用非HTTPS协议访问\n3. 您的设备驱动程序有问题\n\n建议尝试更换浏览器或使用HTTPS访问。');

          // 尝试降级到仅音频
          try {
            console.log('尝试仅使用音频...');
            const audioOnlyStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
            alert('已切换到仅音频模式。');
            return audioOnlyStream;
          } catch (audioError) {
            console.error('获取音频设备也失败:', audioError);
            return null;
          }
        } else if (mediaError.name === 'NotReadableError' || mediaError.name === 'TrackStartError') {
          alert('无法访问摄像头或麦克风，因为它们可能正被其他应用程序使用。请关闭其他可能使用摄像头的应用，然后重试。');
        } else if (mediaError.name === 'OverconstrainedError') {
          alert('您的摄像头不满足要求的规格。请尝试使用其他摄像头。');
        } else if (mediaError.name === 'SecurityError') {
          alert('由于安全限制，无法访问媒体设备。这通常发生在非安全上下文(非HTTPS)中。');
        } else {
          alert(`无法访问摄像头和麦克风，错误详情: ${mediaError.name || '未知'} - ${mediaError.message}`);
        }
      } else {
        alert('获取媒体设备失败，发生未知错误');
      }
      return null;
    }
  }, []);

  const handleStartCallClick = async () => {
    if (!recipient) {
      alert('请先选择一个聊天对象！');
      return;
    }

    // 检查设备状态
    if (!deviceStatus.checked) {
      await checkMediaDevices();
    }

    // 根据设备状态决定请求哪些媒体
    let mediaConstraints = {};
    if (deviceStatus.hasCamera && deviceStatus.hasMicrophone) {
      mediaConstraints = { video: true, audio: true };
    } else if (deviceStatus.hasCamera) {
      mediaConstraints = { video: true, audio: false };
      alert('将以仅视频模式进行通话，因为未检测到麦克风。');
    } else if (deviceStatus.hasMicrophone) {
      mediaConstraints = { video: false, audio: true };
      alert('将以仅音频模式进行通话，因为未检测到摄像头。');
    } else {
      // 如果两者都没有，给出提示并尝试使用默认设置
      alert('未检测到摄像头和麦克风。请确保设备已连接并授予权限后重试。');
      mediaConstraints = { video: true, audio: true }; // 仍然尝试使用默认设置
    }

    try {
      const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
      if (stream) {
        setLocalStream(stream);
        setCallPartner(recipient);
        startCall(stream);
      }
    } catch (error) {
      console.error('获取媒体流失败:', error);
      // 如果出错，交给getMedia函数处理
      const stream = await getMedia();
      if (stream) {
        setLocalStream(stream);
        setCallPartner(recipient);
        startCall(stream);
      }
    }
  };

  const handleAnswerCallClick = async () => {
    // 检查设备状态
    if (!deviceStatus.checked) {
      await checkMediaDevices();
    }

    // 根据设备状态决定请求哪些媒体
    let mediaConstraints = {};
    if (deviceStatus.hasCamera && deviceStatus.hasMicrophone) {
      mediaConstraints = { video: true, audio: true };
    } else if (deviceStatus.hasCamera) {
      mediaConstraints = { video: true, audio: false };
      alert('将以仅视频模式接听通话，因为未检测到麦克风。');
    } else if (deviceStatus.hasMicrophone) {
      mediaConstraints = { video: false, audio: true };
      alert('将以仅音频模式接听通话，因为未检测到摄像头。');
    } else {
      // 如果两者都没有，给出提示并尝试使用默认设置
      alert('未检测到摄像头和麦克风。请确保设备已连接并授予权限后重试。');
      mediaConstraints = { video: true, audio: true }; // 仍然尝试使用默认设置
    }

    try {
      const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
      if (stream) {
        setLocalStream(stream);
        answerCall(stream);
      }
    } catch (error) {
      console.error('获取媒体流失败:', error);
      // 如果出错，交给getMedia函数处理
      const stream = await getMedia();
      if (stream) {
        setLocalStream(stream);
        answerCall(stream);
      }
    }
  };

  // --- WebSocket 连接与主消息循环 (最终版) ---
  const connect = useCallback(() => {
    if (!userId || (socketRef.current && socketRef.current.readyState === WebSocket.OPEN)) {
      return;
    }

    setConnectionStatus('connecting');
    console.log(`[WebSocket] 正在尝试连接... (第 ${retryCountRef.current + 1} 次)`);

    // 清理旧的实例以防万一
    if (socketRef.current) {
      socketRef.current.onopen = null;
      socketRef.current.onmessage = null;
      socketRef.current.onclose = null;
      socketRef.current.onerror = null;
      if (socketRef.current.readyState !== WebSocket.CLOSED) {
        socketRef.current.close();
      }
    }

    // 根据配置决定使用本地地址还是localtunnel地址
    let wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    let wsHost, wsUrl;

    if (USE_LOCALTUNNEL) {
      // 使用localtunnel地址
      wsProtocol = 'wss:'; // localtunnel总是使用HTTPS，所以WebSocket也用WSS
      wsHost = LOCALTUNNEL_WS_URL;
      wsUrl = `${wsProtocol}//${wsHost}?userId=${userId}`;
      console.log(`[WebSocket] 使用localtunnel连接: ${wsUrl}`);
    } else {
      // 使用本地地址
      wsHost = window.location.hostname;
      // 强制使用ws协议，因为后端已改为HTTP服务器
      wsProtocol = 'ws:';
      // 使用正确的端口号和协议
      wsUrl = `${wsProtocol}//${LOCALTUNNEL_WS_URL}?userId=${userId}`;

      // 确保userId是唯一的，避免连接冲突
      wsUrl += `&t=${Date.now()}`;

      console.log(`[WebSocket] 使用本地连接: ${wsUrl}`);
    }

    try {
      const ws = new WebSocket(wsUrl);
      socketRef.current = ws;

      ws.onopen = () => {
        console.log('[WebSocket] 连接成功!');
        setIsOnline(true);
        setConnectionStatus('online');
        retryCountRef.current = 0; // 重置重连计数
        // 清除可能存在的重连定时器
        if (reconnectTimerRef.current) {
          clearTimeout(reconnectTimerRef.current);
          reconnectTimerRef.current = null;
        }
      };

      ws.onmessage = async (event) => {
        try {
          const data = JSON.parse(event.data);
          // 安全地访问stateRef.current
          const callStateValue = stateRef.current?.callState || 'idle';
          const peerConnectionValue = stateRef.current?.peerConnection;

          switch (data.type) {
            case 'start-call':
              if (callStateValue === 'idle') {
                console.log('Received call offer:', data);
                setIncomingCall({ from: data.from, offer: data.offer });
                setCallPartner(data.from); // 新增：设置通话伙伴
                setCallState('receiving');
              }
              break;
            case 'webrtc-answer':
              if (peerConnectionValue && callStateValue === 'calling') {
                console.log('Received answer:', data);
                try {
                  console.log('Setting remote description (answer)');
                  await peerConnectionValue.setRemoteDescription(new RTCSessionDescription(data.answer));
                  setCallState('active');
                } catch (err) {
                  console.error('Error setting remote description:', err);
                }
              }
              break;
            case 'webrtc-ice-candidate':
              if (peerConnectionValue) {
                try {
                  console.log('Received ICE candidate:', data.candidate);
                  await peerConnectionValue.addIceCandidate(new RTCIceCandidate(data.candidate));
                  console.log('ICE candidate added successfully');
                } catch (error) {
                  console.error("Error adding ICE candidate:", error);
                }
              } else {
                console.warn('Received ICE candidate but no peer connection exists');
              }
              break;
            case 'ice-timeout':
              console.warn(`收到来自 ${data.from} 的ICE连接超时消息: ${data.message}`);
              alert(`与 ${data.from} 的连接遇到问题: ${data.message}`);
              break;
            case 'end-call':
              if (stateRef.current && stateRef.current.callState !== 'idle') {
                console.log(`Received 'end-call' from ${data.from}. Cleaning up.`);
                stateRef.current.cleanupCall();
              }
              break;
            // --- 其他消息 ---
            case 'welcome': break;
            case 'userList':
              // 检查数据格式并转换为User对象
              const otherUsers = data.users
                .filter((u: string | User) => {
                  const id = typeof u === 'string' ? u : u.id;
                  return id !== userId;
                })
                .map((u: string | User) => {
                  // 如果是字符串ID，转换为User对象
                  if (typeof u === 'string') {
                    return {
                      id: u,
                      name: u // 使用ID作为名称
                    };
                  }
                  // 如果已经是User对象，直接返回
                  return u;
                });

              console.log('处理后的用户列表:', otherUsers);
              setOnlineUsers(otherUsers);

              if (stateRef.current && !stateRef.current.recipient && otherUsers.length > 0) {
                setRecipient(otherUsers[0].id);
              }
              break;
            case 'privateMessage':
            case 'imageMessage':
            case 'videoMessage':
              // 全新的消息处理逻辑
              setChatLog(prev => {
                // 1. 如果是服务器回传的本地消息，忽略它
                if (data.from === userId && data.to === recipient &&
                  prev.some(msg => msg.isLocalMessage && msg.id && msg.id.startsWith('local_'))) {
                  return prev;
                }

                // 2. 如果是接收到的新消息，添加它
                return [...prev, data];
              });
              break;
            case 'error':
              alert(data.message);
              break;
            default:
              console.warn('收到未知类型的消息:', data);
          }
        } catch (error) {
          console.error('Error handling WebSocket message:', error);
        }
      };

      ws.onclose = (event) => {
        console.log(`[WebSocket] 连接已关闭。代码: ${event.code}, 原因: ${event.reason}`);
        setIsOnline(false);
        setConnectionStatus('offline');
        socketRef.current = null;

        // 如果不是正常关闭，则启动重连机制
        if (event.code !== 1000) {
          setConnectionStatus('reconnecting');
          const delay = Math.min(
            RECONNECT_TIMEOUT_BASE * Math.pow(2, retryCountRef.current),
            RECONNECT_TIMEOUT_MAX
          );

          console.log(`[WebSocket] 将在 ${delay / 1000} 秒后尝试重连...`);
          reconnectTimerRef.current = setTimeout(() => {
            retryCountRef.current++;
            connect();
          }, delay);
        }
      };

      ws.onerror = (error) => {
        console.error('[WebSocket] 发生错误:', error);
        // onerror 会自动触发 onclose，所以重连逻辑会由 onclose 处理
        ws.close();
      };
    } catch (error) {
      console.error('Error connecting to WebSocket:', error);
      // 如果WebSocket连接失败，尝试重新连接
      setTimeout(() => {
        retryCountRef.current++;
        connect();
      }, RECONNECT_TIMEOUT_BASE);
    }
  }, [userId]); // <-- 依赖项已简化，非常稳定

  // --- 登录和退出逻辑 ---
  const handleLogin = () => {
    if (userId.trim()) {
      retryCountRef.current = 0; // 每次手动登录时重置计数
      connect();
    } else {
      alert('请输入一个有效的用户ID。');
    }
  };

  const handleLogout = useCallback(() => {
    console.log('用户退出，清理资源...');

    // 如果正在通话中，先挂断
    if (stateRef.current && stateRef.current.callState !== 'idle') {
      stateRef.current.cleanupCall();
    }

    // 清理WebSocket连接
    if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
      // 发送退出消息给服务器
      try {
        socketRef.current.send(JSON.stringify({ type: 'logout' }));
        // 给服务器一点时间处理退出消息
        setTimeout(() => {
          if (socketRef.current) {
            socketRef.current.onclose = null; // 禁用重连逻辑
            socketRef.current.close(1000, '用户主动退出');
            socketRef.current = null;
          }
        }, 100);
      } catch (error) {
        console.error('发送退出消息失败:', error);
        socketRef.current.onclose = null;
        socketRef.current.close(1000, '用户主动退出');
        socketRef.current = null;
      }
    }

    // 清理定时器
    if (reconnectTimerRef.current) {
      clearTimeout(reconnectTimerRef.current);
      reconnectTimerRef.current = null;
    }
    if (flashTimerRef.current) {
      clearTimeout(flashTimerRef.current);
      flashTimerRef.current = null;
    }

    // 重置所有状态
    setIsOnline(false);
    setConnectionStatus('offline');
    setRecipient('');
    setMessage('');
    setChatLog([]);
    setOnlineUsers([]);
    setShowEmojiPicker(false);
    setIsLightboxOpen(false);
    setCurrentImageIndex(0);
    setChatImages([]);
    setBurnedMessageIds(new Set());
    setActiveFlashMessage(null);
    setCallState('idle');
    setIncomingCall(null);
    setLocalStream(null);
    setRemoteStream(null);

    // 重置重连计数
    retryCountRef.current = 0;
  }, []);

  // 组件卸载时，清理所有资源
  useEffect(() => {
    return () => {
      console.log('[Liaotian] 组件卸载，清理资源...');
      handleLogout();
    };
  }, [handleLogout]);

  // 2. 添加处理隐藏用户的函数
  const handleHideUser = (e: React.MouseEvent, userToHide: User) => {
    e.stopPropagation(); // 防止点击删除按钮时选中该用户
    setHiddenUsers(prev => [...new Set([...prev, userToHide.id])]);

    // 如果当前正在与该用户聊天，则清空聊天窗口
    if (recipient === userToHide.id) {
      setRecipient('');
    }
  };

  // 发送消息
  const sendMessage = () => {
    if (!recipient.trim() || !message.trim()) {
      alert('请选择聊天对象并输入消息内容。');
      return;
    }

    const msgId = `local_${Date.now()}`;
    const timestamp = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

    const payload = {
      type: 'privateMessage',
      to: recipient,
      content: message,
      id: msgId
    };

    if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
      socketRef.current.send(JSON.stringify(payload));

      // 将自己发送的消息直接添加到聊天记录，不等待服务器回应
      const localMsg: ChatMessage = {
        ...payload,
        from: userId,
        timestamp: timestamp,
        isLocalMessage: true // 标记为本地消息
      };

      setChatLog(prev => [...prev, localMsg]);
      setMessage('');
    } else {
      alert('连接已断开，请重新登录。');
    }
  };

  // --- 文件选择与发送 ---
  const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>, isFlash = false) => {
    const file = event.target.files?.[0];
    if (file && file.type.startsWith('image/')) {
      if (!recipient) {
        alert('请先选择一个聊天对象！');
        return;
      }

      const reader = new FileReader();
      reader.onload = (e: ProgressEvent<FileReader>) => {
        const base64Image = e.target?.result;
        if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
          const msgId = `local_${Date.now()}`;
          const timestamp = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

          const msgPayload = {
            type: 'imageMessage',
            to: recipient,
            content: base64Image,
            isFlash: isFlash,
            id: msgId
          };

          socketRef.current.send(JSON.stringify(msgPayload));

          // 将自己发送的图片直接添加到聊天记录，不等待服务器回应
          const localMsg: ChatMessage = {
            ...msgPayload,
            content: typeof msgPayload.content === 'string' ? msgPayload.content : null,
            from: userId,
            timestamp: timestamp,
            isLocalMessage: true // 标记为本地消息
          };

          setChatLog(prev => [...prev, localMsg]);
        } else {
          alert('连接已断开，请重新登录。');
        }
      };
      reader.readAsDataURL(file);
    }
    // 清空input的值，以便可以连续选择同一个文件
    event.target.value = '';
  };

  // 新增：视频文件选择与发送
  const handleVideoSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file || !file.type.startsWith('video/')) {
      return;
    }

    if (!recipient) {
      alert('请先选择一个聊天对象！');
      event.target.value = '';
      return;
    }

    // 视频大小限制（5MB）
    const MAX_SMALL_VIDEO_SIZE = 5 * 1024 * 1024; // 5MB
    const isLargeVideo = file.size > MAX_SMALL_VIDEO_SIZE;

    if (isLargeVideo) {
      // 大视频处理 - 上传到服务器
      handleLargeVideoUpload(file);
    } else {
      // 小视频处理 - 直接Base64编码发送
      const reader = new FileReader();
      reader.onload = (e: ProgressEvent<FileReader>) => {
        const base64Video = e.target?.result;
        sendVideoMessage(base64Video as string, false, {
          filename: file.name,
          filesize: file.size,
          filetype: file.type,
          duration: 0 // 无法直接获取时长，需要额外处理
        });
      };
      reader.readAsDataURL(file);
    }

    // 清空input的值，以便可以连续选择同一个文件
    event.target.value = '';
  };

  // 处理大视频上传
  const handleLargeVideoUpload = async (file: File) => {
    try {
      // 创建表单数据
      const formData = new FormData();
      formData.append('file', file);

      // 显示上传进度提示
      antdMessage.loading('正在上传视频，请稍候...', 0);

      // 构建上传URL，使用相对路径，更适合本地开发和生产环境
      const uploadUrl = '/api/upload/upload-video';

      // 发送到上传API
      const response = await fetch(uploadUrl, {
        method: 'POST',
        body: formData
      });

      if (!response.ok) {
        throw new Error('视频上传失败');
      }

      const data = await response.json();
      antdMessage.destroy();
      antdMessage.success('视频上传成功');

      // 发送视频链接消息
      sendVideoMessage(data.videoUrl, true, {
        filename: file.name,
        filesize: file.size,
        filetype: file.type,
        duration: 0, // 无法直接获取时长
        thumbnail: data.thumbnailUrl || '' // 缩略图URL，如果服务器提供
      });
    } catch (error) {
      console.error('视频上传失败:', error);
      antdMessage.destroy();
      antdMessage.error('视频上传失败，请重试');
    }
  };

  // 发送视频消息
  const sendVideoMessage = (content: string, isLargeVideo: boolean, videoMetadata: {
    filename?: string;
    filesize?: number;
    filetype?: string;
    duration?: number;
    thumbnail?: string;
  }) => {
    if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
      const msgId = `local_${Date.now()}`;
      const timestamp = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

      const msgPayload = {
        type: 'videoMessage' as const,
        to: recipient,
        content: content, // 可能是Base64编码的视频或视频URL
        isLargeVideo: isLargeVideo,
        videoMetadata: videoMetadata,
        id: msgId
      };

      socketRef.current.send(JSON.stringify(msgPayload));

      // 将自己发送的视频消息直接添加到聊天记录
      const localMsg: ChatMessage = {
        ...msgPayload,
        from: userId,
        timestamp: timestamp,
        isLocalMessage: true // 标记为本地消息
      };

      setChatLog(prev => [...prev, localMsg]);
    } else {
      alert('连接已断开，请重新登录。');
    }
  };

  // 3. 从在线用户中过滤掉已隐藏的用户
  const visibleUsers = onlineUsers.filter(user => !hiddenUsers.includes(user.id));

  // 根据连接状态显示不同的标题
  const renderChatHeader = () => {
    if (!recipient) return <div className="chat-header">请选择联系人</div>;

    switch (connectionStatus) {
      case 'online':
        return <div className="chat-header">{recipient}</div>;
      case 'connecting':
        return <div className="chat-header">连接中...</div>;
      case 'reconnecting':
        return <div className="chat-header">与 {recipient} 的连接中断，正在重连...</div>;
      default:
        return <div className="chat-header">{recipient} (离线)</div>;
    }
  };

  // 将媒体流附加到 video 元素 (带强化版日志)
  useEffect(() => {
    if (localVideoRef.current && localStream) {
      console.log("正在挂载本地视频流");
      localVideoRef.current.srcObject = localStream;

      // 添加事件监听器
      const videoEl = localVideoRef.current;

      // 强制设置视频属性
      videoEl.muted = true; // 本地视频必须静音
      videoEl.playsInline = true;
      videoEl.autoplay = true;

      const handleLoadedMetadata = () => {
        console.log("本地视频元数据已加载，强制播放");
        // 强制播放
        const playPromise = videoEl.play();
        if (playPromise !== undefined) {
          playPromise.then(() => {
            console.log('本地视频播放成功');
          }).catch(e => {
            console.error("本地视频播放失败:", e);
            // 用户手动点击后播放
            const playButton = document.createElement('button');
            playButton.textContent = '点击播放视频';
            playButton.style.position = 'absolute';
            playButton.style.zIndex = '2000';
            playButton.style.top = '50%';
            playButton.style.left = '50%';
            playButton.style.transform = 'translate(-50%, -50%)';
            playButton.style.padding = '10px';
            document.body.appendChild(playButton);

            playButton.onclick = () => {
              videoEl.play();
              playButton.remove();
            };
          });
        }
      };

      const handleError = (e: Event) => {
        console.error("本地视频元素错误:", e);
      };

      videoEl.addEventListener('loadedmetadata', handleLoadedMetadata);
      videoEl.addEventListener('error', handleError);

      return () => {
        videoEl.removeEventListener('loadedmetadata', handleLoadedMetadata);
        videoEl.removeEventListener('error', handleError);
      };
    }
  }, [localStream]);

  // 全屏切换处理函数
  const handleToggleFullScreen = () => {
    if (!document.fullscreenElement) {
      if (videoContainerRef.current) {
        videoContainerRef.current.requestFullscreen().catch(err => {
          alert(`进入全屏模式失败: ${err.message} (${err.name})`);
        });
      }
    } else {
      document.exitFullscreen();
    }
  };

  // 监听全屏状态变化
  useEffect(() => {
    const handleFullScreenChange = () => {
      setIsFullScreen(!!document.fullscreenElement);
    };
    document.addEventListener('fullscreenchange', handleFullScreenChange);
    return () => {
      document.removeEventListener('fullscreenchange', handleFullScreenChange);
    };
  }, []);

  // 添加设备状态
  const [deviceStatus, setDeviceStatus] = useState({
    hasCamera: false,
    hasMicrophone: false,
    checked: false
  });

  // 检查媒体设备可用性
  const checkMediaDevices = useCallback(async () => {
    try {
      // 检查浏览器是否支持navigator.mediaDevices
      if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
        console.warn('浏览器不支持媒体设备枚举');
        setDeviceStatus({
          hasCamera: false,
          hasMicrophone: false,
          checked: true
        });
        return false;
      }

      // 枚举设备
      const devices = await navigator.mediaDevices.enumerateDevices();

      // 检查是否有摄像头和麦克风
      const hasCamera = devices.some(device => device.kind === 'videoinput');
      const hasMicrophone = devices.some(device => device.kind === 'audioinput');

      console.log('设备检测结果:', { hasCamera, hasMicrophone });

      setDeviceStatus({
        hasCamera,
        hasMicrophone,
        checked: true
      });

      return hasCamera || hasMicrophone;
    } catch (error) {
      console.error('检测媒体设备失败:', error);
      setDeviceStatus({
        hasCamera: false,
        hasMicrophone: false,
        checked: true
      });
      return false;
    }
  }, []);

  // 在组件挂载时检查设备可用性
  useEffect(() => {
    if (isOnline && !deviceStatus.checked) {
      checkMediaDevices();
    }
  }, [isOnline, deviceStatus.checked, checkMediaDevices]);

  // 渲染登录界面
  if (connectionStatus === 'offline' && !isOnline) {
    return (
      <div className="login-container">
        <div className="login-box">
          <h3>移动端聊天</h3>
          <input
            type="text"
            placeholder="输入你的用户ID"
            value={userId}
            onChange={(e) => setUserId(e.target.value)}
            onKeyPress={(e) => e.key === 'Enter' && handleLogin()}
          />
          <button onClick={handleLogin}>登录</button>
        </div>
      </div>
    );
  }

  // 渲染聊天主界面
  return (
    <div className="chat-app-container">
      {/* 左侧联系人列表 - 添加条件类名 */}
      <div className={`chat-list-panel ${showContactList ? '' : 'hidden'}`}>
        <div className="chat-list-header">
          <div>联系人</div>
          <button className="logout-button" onClick={handleLogout} title="退出登录">
            退出
          </button>
        </div>
        <div className="chat-list">
          {visibleUsers.map(user => (
            <div
              key={user.id}
              className={`chat-list-item ${recipient === user.id ? 'active' : ''}`}
              onClick={() => handleSelectContact(user)}
            >
              <img src={`https://api.dicebear.com/8.x/miniavs/svg?seed=${user.id}`} alt="avatar" className="avatar" />
              <div className="user-info">
                <div className="user-name">{user.name}</div>
              </div>
              {/* 删除按钮 */}
              <button
                className="delete-user-btn"
                title={`隐藏 ${user.name}`}
                onClick={(e) => handleHideUser(e, user)}
              >
                &times;
              </button>
            </div>
          ))}
          {visibleUsers.length === 0 && (
            <div className="no-contacts">暂无在线联系人</div>
          )}
        </div>
      </div>

      {/* 右侧聊天窗口 */}
      <div className="chat-window">
        {recipient ? (
          <>
            <div className="chat-header">
              {/* 添加返回按钮，用于在移动端显示联系人列表 */}
              {!showContactList && (
                <button className="back-button" onClick={showContacts}>
                  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M15 18L9 12L15 6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                  联系人
                </button>
              )}
              <div>
                <div>{recipient}</div>
                <div className="user-status">
                  {connectionStatus === 'online' ? '在线' : '连接中...'}
                </div>
              </div>
              <div className="header-actions">
                <button onClick={handleStartCallClick} disabled={callState !== 'idle'}>
                  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M22 16.92V19.92C22 20.4704 21.7893 20.9978 21.4142 21.3728C21.0391 21.7479 20.5117 21.9585 19.96 21.96C17.4 22.15 14.9 21.73 12.6 20.74C10.4 19.83 8.5 18.39 6.9 16.79C5.3 15.19 3.86 13.29 2.95 11.09C1.96 8.79 1.54 6.28 1.73 3.72C1.7315 3.16927 1.94163 2.64298 2.31536 2.26881C2.68909 1.89465 3.21529 1.68335 3.77 1.68H6.77C7.68579 1.67172 8.51913 2.28115 8.76 3.17C8.93013 3.88249 9.15746 4.57638 9.44 5.24C9.70349 5.8502 9.59883 6.54869 9.17 7.03L8.05 8.15C9.08953 10.3404 10.6596 12.2105 12.6 13.39L13.72 12.27C14.2013 11.8412 14.8998 11.7366 15.51 12C16.1736 12.2825 16.8675 12.5099 17.58 12.68C18.4801 12.9208 19.0917 13.7626 19.08 14.68L22 16.92Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </button>
              </div>
            </div>
            <div className="message-area">
              {chatLog
                // 过滤出当前聊天对象的消息
                .filter(log => (log.from === userId && log.to === recipient) || (log.from === recipient && log.to === userId))
                // 去除重复消息 - 使用更严格的去重逻辑
                .filter((log, index, self) => {
                  // 如果是本地消息，始终保留
                  if (log.isLocalMessage) {
                    return true;
                  }

                  // 如果消息有ID，使用ID判断
                  if (log.id) {
                    // 检查是否有相同ID的本地消息
                    const localMsgWithSameId = self.findIndex(item =>
                      item.isLocalMessage &&
                      item.id &&
                      item.id.replace('local_', '') === log.id.replace('local_', '')
                    );

                    // 如果存在相同ID的本地消息，则忽略服务器消息
                    if (localMsgWithSameId !== -1) {
                      return false;
                    }

                    // 找到当前消息在数组中第一次出现的位置
                    const firstIndex = self.findIndex(item => item.id === log.id);
                    // 如果当前索引等于第一次出现的索引，说明是第一次出现，保留
                    return index === firstIndex;
                  }

                  // 如果没有ID，使用内容+发送者+接收者+类型组合判断
                  const msgSignature = `${log.type}_${log.from}_${log.to}_${log.content}`;
                  const firstIndex = self.findIndex(item =>
                    `${item.type}_${item.from}_${item.to}_${item.content}` === msgSignature
                  );
                  return index === firstIndex;
                })
                .map((log, index) => {
                  const isSent = log.from === userId;
                  const timestamp = log.timestamp || new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

                  // 闪图渲染逻辑
                  if (log.type === 'imageMessage' && log.isFlash) {
                    if (burnedMessageIds.has(log.id)) {
                      return (
                        <div key={log.id || index} className={`message ${isSent ? 'sent' : 'received'}`}>
                          {!isSent && <img src={`https://api.dicebear.com/8.x/miniavs/svg?seed=${log.from}`} alt="avatar" className="avatar" />}
                          <div className="message-content">
                            <div className="flash-image-burned"><span>🔥</span><span>图片已销毁</span></div>
                            <div className="message-timestamp">{timestamp}</div>
                          </div>
                        </div>
                      );
                    }
                    return (
                      <div key={log.id || index} className={`message ${isSent ? 'sent' : 'received'}`}>
                        {!isSent && <img src={`https://api.dicebear.com/8.x/miniavs/svg?seed=${log.from}`} alt="avatar" className="avatar" />}
                        <div className="message-content">
                          <div className="flash-image-placeholder" onClick={() => handleViewFlashImage(log)}>
                            <span>⚡️</span><span>闪图 (点击查看)</span>
                          </div>
                          <div className="message-timestamp">{timestamp}</div>
                        </div>
                      </div>
                    );
                  }

                  // 普通消息和图片渲染逻辑
                  const bubbleType = log.type === 'imageMessage' ? 'image-bubble' : '';
                  let imageIndex = -1;
                  if (log.type === 'imageMessage' && !log.isFlash && typeof log.content === 'string') {
                    imageIndex = chatImages.indexOf(log.content);
                  }
                  return (
                    <div key={log.id || index} className={`message ${isSent ? 'sent' : 'received'}`}>
                      {!isSent && <img
                        src={`https://api.dicebear.com/8.x/miniavs/svg?seed=${log.from}`}
                        alt="avatar"
                        className="avatar"
                      />}
                      <div className="message-content">
                        <div className={`message-bubble ${bubbleType}`}>
                          {log.type === 'imageMessage' ? (
                            <img
                              src={typeof log.content === 'string' ? log.content : ''}
                              alt="聊天图片"
                              onClick={() => !log.isFlash && imageIndex >= 0 && openLightbox(imageIndex)}
                              style={{ cursor: !log.isFlash ? 'pointer' : 'default' }}
                            />
                          ) : log.type === 'videoMessage' ? (
                            // 视频消息渲染逻辑
                            log.isLargeVideo ? (
                              // 大视频渲染（带有链接和缩略图）
                              <div className="video-message">
                                <div className="video-preview">
                                  {log.videoMetadata?.thumbnail ? (
                                    <img
                                      src={log.videoMetadata?.thumbnail || ''}
                                      alt="视频预览"
                                      className="video-thumbnail"
                                    />
                                  ) : (
                                    <div className="video-placeholder">
                                      <span className="video-icon">🎬</span>
                                    </div>
                                  )}
                                  <div className="video-info">
                                    <span className="video-filename">{log.videoMetadata?.filename || "视频"}</span>
                                    <span className="video-filesize">
                                      {log.videoMetadata?.filesize ? `${Math.round(log.videoMetadata.filesize / 1024 / 1024 * 100) / 100} MB` : ""}
                                    </span>
                                  </div>
                                  <a
                                    href={typeof log.content === 'string' ? log.content : '#'}
                                    target="_blank"
                                    rel="noopener noreferrer"
                                    className="video-link"
                                  >
                                    播放视频
                                  </a>
                                </div>
                              </div>
                            ) : (
                              // 小视频渲染（内联播放器）
                              <div className="video-message">
                                <video
                                  controls
                                  className="inline-video"
                                  preload="metadata"
                                >
                                  <source src={typeof log.content === 'string' ? log.content : ''} type={log.videoMetadata?.filetype || "video/mp4"} />
                                  您的浏览器不支持视频播放
                                </video>
                                <div className="video-info">
                                  <span className="video-filename">{log.videoMetadata?.filename || "视频"}</span>
                                </div>
                              </div>
                            )
                          ) : (
                            typeof log.content === 'string' ? log.content : ''
                          )}
                        </div>
                        <div className="message-timestamp">{timestamp}</div>
                      </div>
                    </div>
                  );
                })
              }
              <div ref={messagesEndRef} />
            </div>
            <div className="message-input-area">
              {/* 表情选择器 */}
              {showEmojiPicker && (
                <div ref={emojiPickerRef} className="emoji-picker-container">
                  <EmojiPicker
                    onEmojiClick={handleEmojiClick}
                    autoFocusSearch={false}
                    emojiStyle={"native" as any}
                    height={300}
                    width="100%"
                  />
                </div>
              )}

              <div className="icon-row">
                <button className="emoji-button" title="选择表情" onClick={() => setShowEmojiPicker(!showEmojiPicker)}>
                  😀
                </button>

                <input type="file" ref={flashFileInputRef} style={{ display: 'none' }} accept="image/*" onChange={(e) => handleFileSelect(e, true)} />
                <button className="flash-button" title="发送闪图" onClick={() => flashFileInputRef.current?.click()}>⚡️</button>

                <input type="file" ref={fileInputRef} style={{ display: 'none' }} accept="image/*" onChange={(e) => handleFileSelect(e, false)} />
                <button className="attach-button" title="发送图片" onClick={() => fileInputRef.current?.click()}>📷</button>

                <input type="file" ref={videoFileInputRef} style={{ display: 'none' }} accept="video/*" onChange={handleVideoSelect} />
                <button className="video-button" title="发送视频" onClick={() => videoFileInputRef.current?.click()}>🎬</button>
              </div>

              <div className="input-row">
                <input
                  ref={messageInputRef}
                  type="text"
                  className="message-input"
                  placeholder="输入消息..."
                  value={message}
                  onChange={(e) => setMessage(e.target.value)}
                  onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
                />
                <button onClick={sendMessage} className="send-button">
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <line x1="22" y1="2" x2="11" y2="13"></line>
                    <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
                  </svg>
                </button>
              </div>
            </div>
          </>
        ) : (
          <div className="chat-window-placeholder">
            选择一个用户开始聊天
          </div>
        )}

        {/* 视频通话界面 */}
        {['calling', 'active'].includes(callState) && (
          <div className="video-call-container" ref={videoContainerRef}>
            {/* 远程视频流 */}
            <video
              ref={remoteVideoRef}
              autoPlay
              playsInline
              className="remote-video"
              onClick={() => {
                if (remoteVideoRef.current) {
                  if (remoteVideoRef.current.muted) {
                    remoteVideoRef.current.muted = false;
                    antdMessage.success('已取消静音');
                  }
                  remoteVideoRef.current.play().catch(err => console.error('播放失败:', err));
                }
              }}
            ></video>

            {/* 本地视频流 */}
            <video
              ref={localVideoRef}
              autoPlay
              playsInline
              muted
              className="local-video"
              onClick={() => localVideoRef.current && localVideoRef.current.play()}
            ></video>

            {/* 通话状态 */}
            {callState === 'calling' && <div className="call-status">正在呼叫 {recipient}...</div>}
            {callState === 'active' && !remoteStream && <div className="call-status">等待对方视频...</div>}

            {/* 简化后的控制条 - 只保留挂电话按钮 */}
            <div className="call-controls simplified">
              <button className="control-button hang-up-btn" onClick={handleHangUpClick}>
                📞
              </button>
            </div>

            {/* 连接状态指示器 */}
            <div className="connection-status">
              ICE: {peerConnectionRef.current?.iceConnectionState || 'disconnected'} |
              连接: {peerConnectionRef.current?.connectionState || 'disconnected'}
            </div>
          </div>
        )}

        {/* 来电通知 - 优化样式 */}
        {callState === 'receiving' && incomingCall && (
          <div className="incoming-call-modal">
            <div className="incoming-call-content">
              <div className="caller-avatar">
                <img
                  src={`https://api.dicebear.com/8.x/miniavs/svg?seed=${incomingCall.from}`}
                  alt="avatar"
                />
              </div>
              <div className="caller-info">
                <div className="caller-name">{incomingCall.from}</div>
                <div className="call-type">视频通话</div>
              </div>
              <div className="call-actions">
                <button className="control-button decline-btn call-action-btn" onClick={handleHangUpClick}>❌</button>
                <button className="control-button accept-btn call-action-btn" onClick={handleAnswerCallClick}>📞</button>
              </div>
            </div>
          </div>
        )}
      </div>

      {/* Lightbox / 图片查看器 */}
      {isLightboxOpen && chatImages.length > 0 && (
        <div className="lightbox-overlay" onClick={closeLightbox}>
          <div className="lightbox-content" onClick={e => e.stopPropagation()}>
            <img src={chatImages[currentImageIndex]} alt="放大的图片" />
            <button className="lightbox-close-btn" onClick={closeLightbox}>&times;</button>
            {chatImages.length > 1 && (
              <>
                <button className="lightbox-nav-btn prev" onClick={showPrevImage}>&#10094;</button>
                <button className="lightbox-nav-btn next" onClick={showNextImage}>&#10095;</button>
              </>
            )}
          </div>
        </div>
      )}

      {/* 闪图查看器 */}
      {activeFlashMessage && (
        <div className="flash-viewer-overlay" onClick={() => setActiveFlashMessage(null)}>
          <div className="flash-viewer-content">
            <img src={typeof activeFlashMessage.content === 'string' ? activeFlashMessage.content : ''} alt="闪图" />
            <div className="flash-timer-bar">
              <div className="flash-timer-progress"></div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
